package cloud.keveri.gateway.config.nacos;

import cloud.keveri.base.utils.MapUtils;
import cloud.keveri.gateway.config.api.listener.RulesChangeSubscriber;
import cloud.keveri.gateway.dto.Rule;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.google.common.collect.Maps;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.Executor;

/**
 * <p>
 * 作者：沈自在
 **/
@Getter
@Slf4j
public class BaseNacosCacheSupport {

    protected static final Map<String, List<Listener>> LISTENERS = Maps.newConcurrentMap();
    private final ConfigService configService;
    private final String env;
    private final List<RulesChangeSubscriber> rulesChangeSubscribers;

    public BaseNacosCacheSupport(ConfigService configService,
                                 final String env, final List<RulesChangeSubscriber> rulesChangeSubscribers) {
        this.configService = configService;
        this.env = env;
        this.rulesChangeSubscribers = rulesChangeSubscribers;
    }

    /**
     * 监控数据
     */
    protected void watcherData(final String dataId, final OnChange oc) {
        Listener listener = new Listener() {
            @Override
            public void receiveConfigInfo(final String configInfo) {
                oc.change(configInfo);
            }

            @Override
            public Executor getExecutor() {
                return null;
            }
        };
        oc.change(getConfigAndSignListener(dataId, listener));
        MapUtils.computeIfAbsent(LISTENERS, dataId, key -> new ArrayList<>()).add(listener);
    }

    /**
     * 获取监听文件
     */
    private String getConfigAndSignListener(final String dataId, final Listener listener) {
        String config = null;
        try {
            config = configService.getConfigAndSignListener(dataId, env, 6000, listener);
        } catch (NacosException e) {
            log.error(e.getMessage(), e);
        }
        if (Objects.isNull(config)) {
            config = "{}";
        }
        return config;
    }

    /**
     * 回调函数
     */
    protected interface OnChange {
        void change(String changeData);
    }

    /**
     * ===========以下为监听器方法实现==========================================================================================
     */
    protected void updateGatewayRules(final String configInfo) {
        log.info("[Keveri-Cloud] 监听到网关路由规则变化：{}", configInfo);

        // 1. 解析文件
        JSONArray jsonArray = JSON.parseObject(configInfo).getJSONArray("rules");

        // 2. 严谨检测
        if (Objects.isNull(jsonArray)) {
            return;
        }
        List<Rule> rules = jsonArray.toJavaList(Rule.class);

        // 4. 遍历订阅者
        rulesChangeSubscribers.forEach(subscriber -> subscriber.onRulesChange(rules));
    }
}
